Python 匿名函数
什么是匿名函数
在本节课中,我们将介绍匿名函数的概念。所谓匿名函数,顾名思义,即没有名称的函数。在编程中,为函数或变量取名是一个常见的难题,因为起名往往需要考虑清楚功能、命名规范等方面。就像唐代著名诗人李商隐所写的《无题》古诗一样,尽管有一首 非常出名的《无题》,但实际上李商隐共有15首无题的诗,说明取名也对于古诗来说是一个难题。而在Python中,如果一个函数实现的功能非常简短,那么就可以使用匿名函数来解决命名的难题。匿名函数不需要显式地为其命名,因此适用于一些简单而且不需要复用的功能代码。
lambda表达式
在本节课中,我们将介绍如何使用匿名函数。在Python中,我们可以使用lambda表达式来创建匿名函数。Lambda一词源自希腊字母,如下图所示:
它在数学上常见,表示一个函数的名称。使用lambda表达式可以省去为函数重新命名的烦恼,特别适用于简短且不需要复用的功能代码。
举例来说,我们可以将一个普通函数转化为lambda表达式的形式。比如,我们定义了一个名为add的函数,它接受两个参数x和y,然后将它们相加或连接起来,最后调用add函数并传递参数5和3。对于这种简单的函数,我们可以使用lambda表达式来替代普通函数。如下图所示:
替代的方式是将左侧三行普通函数定义代码,简化为右侧一行lambda表达式。Lambda表达式的规则如下图所示:
在对比普通函数和lambda表达式时,可以看到函数名称对应lambda关键字,参数列表对应lambda表达式的参数,函数体对应lambda表达式的冒号后面的代码。
在lambda表达式中,外层使用括号包裹起来。这个括号的作用相当于给lambda表达式赋值为一个函数对象,如下图所示:
然后我们可以直接调用这个函数。因此,使用lambda表达式,我们可以将一个普通函数转化为更简洁的形式。
Lambda表达式的语法结构包括lambda关键字、参数列表和函数体代码。如下图所示:
下面我们将在代码中创建一个lambda表达式。首先,我们创建一个lambda.py文件,命名为lambda。接着,我们定义一个名为add的普通函数,该函数接受两个参数x和y,然后将它们相加并返回结果。接下来,我们调用add函数,将参数1和2传递给它,然后将结果赋值给一个变量result,并输出这个result的值。代码如下:
def add(x,y):
return x+y
result = add(1,2)
print(result)
print(add)
输出结果:
3
现在,我们用lambda表达式来改造这个函数。创建lambda表达式时,我们使用关键字lambda,然后定义两个参数x和y,接着是冒号,再接下来是函数体,即x+y。我们将lambda表达式的值赋给一个变量expression,并输出它的值。代码如下:
def add(x,y):
return x+y
result = add(1,2)
print(result)
print(add)
expression = lambda x,y: x+y
print(expression)
输出结果:
3
<function add at 0x10a59beb0>
<function <lambda> at 0x10a7dc1f0>
当我们运行代码后,可以看到输出的值是一个function。同样地,当我们输出普通函数add时,结果也是一个function。对于lambda表达式的调用,我们依然使用括号并传递参数1和2。结果仍然是3。从这个例子中可以看出,lambda表达式就像是创建了一个add函数一样。调用时,对于普通函数是使用add括号传递参数,而对于lambda表达式也是一样,使用括号传递参数。此外,我们还可以使用简写形式,直接将lambda表达式输出为一个函数,并将参数传递给它。在Python中,语法要求使用括号将lambda表达式括起来,以便正确解析。代码如下:
def add(x,y):
return x+y
result = add(1,2)
print(result)
print(add)
expression = lambda x,y: x+y
print(expression)
print(expression(1,2))
result = (lambda x,y: x+y)(1,2)
print(result)
输出结果:
3
<function add at 0x103ef3eb0>
<function <lambda> at 0x1041341f0>
3
3
最终的输出结果仍然是3。因此,通常情况下,我们直接使用lambda表达式的这种形式。
匿名函数与常规函数区别
本节课的内容是介绍匿名函数和常规函数之间的区别。首先,我们来讨论匿名函数,也就是lambda表达式。它与常规函数的第一个区别在于,lambda表达式是一个表达式而不是语句。其次,lambda表达式的主体通常只包含一行简单的表达式,无法扩展成多行代码块。因此,使用lambda表达式创建的函数在逻辑上应该简单明 了,不应该过于复杂。对于功能比较复杂的函数,我们仍然需要使用普通的函数来创建。
重点来说,lambda表达式是一个表达式而不是一个语句。那么,表达式和语句有何区别呢?如下图所示:
表达式是用一系列公式来表达一个东西,而语句则是完成某些功能。举例来说,x+2、x**2(表示x的平方)、x>2都是表达式。而赋值语句如x=1,最终结果是将1赋值给变量x;而print("hello")则是一个语句,因为它在屏幕上打印出了"hello"。if语句、for循环、while循环等也属于语句,因为它们实现了特定的功能。而lambda表达式是一个表达式,用于表达一个东西而不返回结果。因此,lambda表达式通常与其他内容配合使用,而不会单独使用。
接下来我们将在代码中演示如何使用lambda表达式结合其他内容来实现特定功能。首先,我们创建一个Python文件,命名为lambda_apply。我们先回顾一下列表生成式的使用,例如使用for循环生成0到9的列表,并将每个元素求平方并存储在一个名为result的变量中,最后打印出result的值。代码如下:
# 列表中使用lambda
result = [x ** 2 for x in range(10)]
print(result)
输出结果 :
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
接下来我们介绍了如何使用普通函数来实现这个列表生成式的功能。代码如下:
# 列表中使用lambda
def multiple(x):
return x**2
print([multiple(x) for x in range(10)])
输出结果:
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
现在,为了对比效果,我们将使用lambda表达式来修改这个函数。通过对比运行结果,我们可以看到lambda表达式与普通函数实现了相同的功能。代码如下:
# 列表中使用lambda
print([(lambda x:x**2)(x) for x in range(10)])
输出结果:
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
接下来我们来介绍第二个例子,涉及到结合使用 sort 函数。 sort 函数可以实现对列表进行排序的功能。比如说,如果现在我有一个列表,命名为 list_value,它的值可以是任意的。我们可以对它进行排序。那么如何使用 sort 函数进行排序呢?我们使用 list_value.sort(),排序完成后,这个 list_value 就会被修改,然后我们输出它。代码如下:
# 结合sort()函数
list_value = [32,13,64,5,88]
list_value.sort()
print(list_value)
输出结果:
[5, 13, 32, 64, 88]
结果会按照从小到大的顺序排列。如果要按照从大到小的顺序排序呢?这时候我们需要了解一下 sort 函数的语法格式。语法格式如下:
list.sort(key=None, reverse=False)
sort 函数有两个参数,一个是 key,表示根据什么进行排序;第二个是 reverse,表示是否降序排序。如果我们要从高到低进行排序,就需要设置 reverse 为 True,表示倒序排序。代码如下:
# 结合sort()函数, list.sort(key=None, reverse=False)
list_value = [32,13,64,5,88]
list_value.sort(reverse=True)
print(list_value)
输出结果:
[88, 64, 32, 13, 5]
接下来我们创建一个特殊的列表,命名为 list_value2,其中每个元素都是一个元组。现在我们对它进行排序,按照升序排列。代码如下:
list_value2 = [(5,6),(7,3),(1,8)]
list_value2.sort()
print(list_value2)
输出结果:
[(1, 8), (5, 6), (7, 3)]
然后再来看一下结果。我们可以看到,输出的结果是根据第一个值进行排序的,这是一个升序排列。如果要进行降序排列,就需要在 sort 函数中设置 reverse=True。
但是如果我们希望根据这个元组中的第二个元素进行排序,那么之前的方法就不再适用了。这时候就需要使用 sort 函数的第二个参数 key,来指定根据什么进行排序。那么如何指定这个 key 呢?我们可以将 key 设置为一个函数,比如我们可以定义一个函数 take_second,它的参数是 list_val,然后我们对 list_val 进行操作,取出第二个元素,即索引为 1 的元素,然后返回结果。然后在 sort 函数中,指定 key 为这个函数名 take_second,这样就实现了根据第二个元素进行排序。代码如下:
# 定义一个函数 take_second,参数为列表 list_val
def take_second(list_val):
return list_val[1] # 返回列表中的第二个元素
# 创建一个特殊的列表 list_value2,其中每个元素都是一个元组
list_value2 = [(5, 6), (7, 3), (1, 8)]
# 使用 sort 函数对 list_value2 进行排序,指定 key 参数为 take_second 函数
list_value2.sort(key=take_second)
# 输出排序后的 list_value2
print(list_value2)
输出结果:
[(7, 3), (5, 6), (1, 8)]
不过,这种方式使用了 def 来定义函数,有些繁琐。这时候就可以考虑使用 lambda 表达式来简化。我们可以直接将函数 take_second 替换为 lambda 表达式。这样我们就可以在代码中省去定义函数的步骤,更加简洁。代码如下:
list_value2 = [(5,6),(7,3),(1,8)]
list_value2.sort(key=lambda x:x[1],reverse=True)
print(list_value2)
通过这种方式,我们实现了根据第二个元素进行排序。此外,lambda 表达式还可以与 map 函数、filter 函数等进行结合使用,这些内容我们会在函数式编程的课程中进行讲解。
匿名函数的应用场景
本节课我们将探讨为何要使用匿名函数,即 lambda 表达式的应用场景。普通函数通常有两个主要作用:一是减少代码的重复性,二是实现模块化的代码。然而,对于一些简单的功能,比如求和、求平方等,再定义一个新的函数就显得有些多余。在这种情况下,使用 lambda 表达式能够轻松解决这个问题,它的作用是简化代码并提高可读性。需要注意的是,lambda 表达式的形式限制在一行内,不支持多行形式。因此,它适用于程序中需要使用一个函数完成简单功能,并且这个函数只调用一次的情况。